﻿using System;
using System.Linq;
using System.Collections.Generic;

namespace PortalCurriculo.Domain
{
    public partial class Curriculo : Interface.ICurriculo
    {
        public class Pesquisa
        {
            public Curriculo Curriculo { get; set; }
            public int Relevancia { get; set; }
        }

        public List<Curriculo> SelecionarPorProfissional()
        {
            return (from curriculo in Context.Instance.Curriculoes
                    where curriculo.IdProfissional.Equals(IdProfissional)
                    && curriculo.Ativo
                    select curriculo).ToList();
        }

        public List<Pesquisa> ListarPorPalavraChave(string palavraChave, int idCidade, int idUnidadeFederativa, int idPais)
        {
            var pesquisas = new List<Pesquisa>();
            var palavraChaveSplited = palavraChave.Split(' ').ToList();

            var dataInicial = DateTime.Today.AddDays(-30);

            foreach (var palavra in palavraChaveSplited)
            {
                //var teste =  Context.Instance.Curriculoes.Where(c => (c.Profissional.Usuario.Pessoa.Enderecoes != null
                //&&(c.Profissional.Usuario.Pessoa.Enderecoes.First().CEP.Bairro.Cidade.UnidadeFederativa.Pai.Id.Equals(idPais)|| idPais == 0)
                //&&(c.Profissional.Usuario.Pessoa.Enderecoes.First().CEP.Bairro.Cidade.UnidadeFederativa.Id.Equals(idUnidadeFederativa)|| idUnidadeFederativa == 0)
                //&&(c.Profissional.Usuario.Pessoa.Enderecoes.First().CEP.Bairro.Cidade.Id.Equals(idCidade)|| idCidade == 0)) && c.DataUltimaAtualizacao > dataInicial);
                int valor = ObterValorRelevancia(palavraChaveSplited, palavra);
                var pesquisasNovas = ListarPorPalavraChave(Context.Instance.Curriculoes.Where(c => c.DataUltimaAtualizacao > dataInicial), palavra, valor);
                AdicionarPesquisasUnicas(pesquisas, pesquisasNovas);

                if (palavraChaveSplited.IndexOf(palavra) == 0) continue;

                var curriculos = SelecionarCurriculosPesquisados(pesquisas);
                pesquisasNovas = ListarPorPalavraChave(curriculos, palavra, valor);
                AdicionarPesquisasUnicas(pesquisas, pesquisasNovas);
            }

            return pesquisas
                .Where(c => c.Curriculo.Profissional.Usuario.Pessoa.Enderecoes != null
                            && (c.Curriculo.Profissional.Usuario.Pessoa.Enderecoes.First().CEP.Bairro.Cidade.UnidadeFederativa.Pai.Id.Equals(idPais)
                                || idPais == 0)
                            && (c.Curriculo.Profissional.Usuario.Pessoa.Enderecoes.First().CEP.Bairro.Cidade.UnidadeFederativa.Id.Equals(idUnidadeFederativa)
                                || idUnidadeFederativa == 0)
                            && (c.Curriculo.Profissional.Usuario.Pessoa.Enderecoes.First().CEP.Bairro.Cidade.Id.Equals(idCidade)
                                || idCidade == 0))
                .Distinct().OrderByDescending(p => p.Relevancia).ThenByDescending(p => p.Curriculo.DataUltimaAtualizacao).ToList();
        }

        private static void AdicionarPesquisasUnicas(List<Pesquisa> pesquisas, IEnumerable<Pesquisa> pesquisasNovas)
        {
            foreach (var pesquisaNova in pesquisasNovas)
            {
                var pesquisaAntiga = pesquisas.Where(p => p.Curriculo.Id == pesquisaNova.Curriculo.Id).FirstOrDefault();

                if (pesquisaAntiga == null)
                    pesquisas.Add(pesquisaNova);
                else
                    pesquisaAntiga.Relevancia += pesquisaNova.Relevancia;
            }
        }

        private IQueryable<Curriculo> SelecionarCurriculosPesquisados(IEnumerable<Pesquisa> pesquisas)
        {
            var idsCurriculo = pesquisas.Select(pesquisa => pesquisa.Curriculo.Id).ToList();
            return Context.Instance.Curriculoes.Where(c => idsCurriculo.Contains(c.Id));
        }

        private int ObterValorRelevancia(IEnumerable<string> palavraChaveSplited, string palavra)
        {
            return (palavraChaveSplited.Reverse().ToList().IndexOf(palavra) + 1) * 20;
        }

        private static IEnumerable<Pesquisa> ListarPorPalavraChave(IQueryable<Curriculo> curriculos,
                                                                   string palavra, int valor)
        {
            return (from curriculo in curriculos
                    join acaoSocial in Context.Instance.AcaoSocials.DefaultIfEmpty() on curriculo.Id equals
                        acaoSocial.IdCurriculo into joinAcaoSocial
                    from acaoSocial in joinAcaoSocial.DefaultIfEmpty()
                    join cargoCurriculo in Context.Instance.CargoCurriculoes.DefaultIfEmpty() on curriculo equals
                        cargoCurriculo.Curriculo into joinCargo
                    from cargoCurriculo in joinCargo.DefaultIfEmpty()
                    join conhecimentoCurriculo in Context.Instance.ConhecimentoCurriculoes.DefaultIfEmpty() on
                        curriculo.Id equals
                        conhecimentoCurriculo.IdCurriculo into joinConhecimento
                    from conhecimentoCurriculo in joinConhecimento.DefaultIfEmpty()
                    join especializacao in Context.Instance.Especializacaos.DefaultIfEmpty() on curriculo.Id equals
                        especializacao.IdCurriculo into joinEspecializacao
                    from especializacao in joinEspecializacao.DefaultIfEmpty()
                    join experienciaProfissional in Context.Instance.ExperienciaProfissionals.DefaultIfEmpty() on
                        curriculo.Id equals
                        experienciaProfissional.IdCurriculo into joinExperienciaProfissional
                    from experienciaProfissional in joinExperienciaProfissional.DefaultIfEmpty()
                    join idiomaCurriculo in Context.Instance.IdiomaCurriculoes.DefaultIfEmpty() on curriculo.Id equals
                        idiomaCurriculo.IdCurriculo into joinIdiomaCurriculo
                    from idiomaCurriculo in joinIdiomaCurriculo.DefaultIfEmpty()
                    join informacao in Context.Instance.InformacaoCurriculoes.DefaultIfEmpty() on curriculo.Id equals
                        informacao.IdCurriculo into joinInformacao
                    from informacao in joinInformacao.DefaultIfEmpty()
                    join projeto in Context.Instance.ProjetoDesenvolvidoes.DefaultIfEmpty() on curriculo.Id equals
                        projeto.IdCurriculo into joinProjeto
                    from projeto in joinProjeto.DefaultIfEmpty()
                    join endereco in Context.Instance.Enderecoes on curriculo.Profissional.Usuario.Pessoa.Id equals
                        endereco.IdPessoa
                    where //Currículo
                           curriculo.Objetivo.Contains(palavra)
                        //Ação Social
                           || acaoSocial.Descricao.Contains(palavra)
                        //Cargo
                           || cargoCurriculo.Cargo.Descricao.Contains(palavra)
                           || cargoCurriculo.Cargo.EspecializacaoArea.Descricao.Contains(palavra)
                           || cargoCurriculo.Cargo.EspecializacaoArea.Area.Descricao.Contains(palavra)
                        //Conhecimento
                           || conhecimentoCurriculo.Conhecimento.Descricao.Contains(palavra)
                        //Especialização
                           || especializacao.Descricao.Contains(palavra)
                           || especializacao.Titulo.Contains(palavra)
                           || especializacao.NivelEspecializacao.Descricao.Contains(palavra)
                           || especializacao.NivelEspecializacao.TipoEspecializacao.Descricao.Contains(palavra)
                           || especializacao.TipoEspecializacao.Descricao.Contains(palavra)
                        //Experiência profissional
                           || experienciaProfissional.Descricao.Contains(palavra)
                           || experienciaProfissional.Empresa.Contains(palavra)
                           || experienciaProfissional.FormaContratacao.Descricao.Contains(palavra)
                        //Idioma
                           || idiomaCurriculo.Outro.Contains(palavra)
                           || idiomaCurriculo.Idioma.Descricao.Contains(palavra)
                           || idiomaCurriculo.Nivel.Descricao.Contains(palavra)
                        //Informação
                           || informacao.Descricao.Contains(palavra)
                        //Projeto
                           || projeto.Descricao.Contains(palavra)
                           || projeto.Cliente.Contains(palavra)
                           || projeto.Titulo.Contains(palavra)
                        //Profissional
                           //|| curriculo.Profissional.CartaApresentacao.Contains(palavra)
                    select new Pesquisa { Curriculo = curriculo, Relevancia = valor }).Distinct();
        }

        public bool Existe(int idProfissional, string objetivo)
        {
            return Context.Instance.Curriculoes.Any(d => d.IdProfissional == idProfissional && d.Objetivo == objetivo);
        }
    }
}
